from enum import Enum
from collections import OrderedDict, defaultdict
from typing import List, Set, Callable, Dict
from abc import ABC, abstractmethod

from data import Content

class LRUCacheF:
    def __init__(self, capacity: int) -> None:
        self.cache = OrderedDict()
        self.capacity = capacity
        self.used = 0

    def _loc(self, vid: int) -> Content:
        return self.cache.get(vid)

    def _evict(self, need) -> None:
        while self.used + need > self.capacity:
            item = self.cache.popitem()
            self.used -= len(item[1].slice)

    def get(self, content: Content) -> bool:
        item = self._loc(content.vid)
        if item is not None and content.slice in item.slice:
            self.cache.move_to_end(content.vid, last=False)
            return True
        return False

    def put(self, content: Content) -> bool:
        item = self._loc(content.vid)
        # Move content to the front
        if item is not None:
            assert content.slice in item.slice
            self.cache.move_to_end(content.vid, last=False)
            return True
        # Evict old content
        self._evict(len(content.slice))
        # Add new content
        self.cache[content.vid] = content
        self.used += len(content.slice)
        self.cache.move_to_end(content.vid, last=False)
        return True

    def items(self) -> List[Content]:
        return list(self.cache.values())
